package cn.wzb.hrm.service.impl;

import cn.wzb.hrm.dto.VerifSMSCodeDto;
import cn.wzb.hrm.feignclient.RedisFeignClient;
import cn.wzb.hrm.service.IVerifyCodeService;
import cn.wzb.hrm.util.AjaxResult;
import cn.wzb.hrm.util.HttpUtil;
import cn.wzb.hrm.util.StrUtils;
import cn.wzb.hrm.util.VerifyCodeUtils;
import cn.wzb.hrm.vo.SMSCodeVo;
import com.alibaba.fastjson.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

@Service
public class VerifyCodeServiceImpl implements IVerifyCodeService {

    @Autowired
    private RedisFeignClient redisFeignClient ;

    @Override
    public String createImageCode(String imageCodeKey) {
        //1.判断参数
        if(!StringUtils.hasLength(imageCodeKey)){
            throw new RuntimeException("无效的imageCodeKey");
        }

        //2.图片验证码的值创建 imageCodeValue
        String imageCodeValue = UUID.randomUUID().toString().substring(0, 4);

        //3.把图片验证码的值放到Redis , 以 imageCodeKey作为key :imageCodeKey =  imageCodeValue
        //并设置过期时间
        //参数： 验证码的key ,过期时间 ， 验证码的值
        AjaxResult imageCodeResult = redisFeignClient.setex(imageCodeKey, 600, imageCodeValue);
        if(!imageCodeResult.isSuccess()){
            throw new RuntimeException("验证码获取失败，缓存服务不可用");
        }

        String base64String = VerifyCodeUtils.verifyCode(150, 40, imageCodeValue);

        //6.返回base64编码成字符串
        return base64String;
    }

    @Override
    public void sendSmsCode(VerifSMSCodeDto verifSMSCodeDto) {
        //前台传入的图片验证码
        String imageCode = verifSMSCodeDto.getImageCode();
        //图片验证码Redis的key
        String imageCodeKey = verifSMSCodeDto.getImageCodeKey();
        //手机号-->接收短信
        String mobile = verifSMSCodeDto.getMobile();


        //1.参数判断
        if(!StringUtils.hasLength(imageCode)){
            throw new RuntimeException("无效的图片验证码");
        }
        if(!StringUtils.hasLength(imageCodeKey)){
            throw new RuntimeException("无效的图片验证码");
        }
        if(!StringUtils.hasLength(mobile)){
            throw new RuntimeException("无效的手机号");
        }

        //2.比较图片验证码是否正确：拿到redis中的图片验证码和前台传入的验证码比较
        AjaxResult imageCodeAjaxResult = redisFeignClient.getString(imageCodeKey);
        if(!imageCodeAjaxResult.isSuccess() || imageCodeAjaxResult.getResultObj() == null){
            throw new RuntimeException("无效的图片验证码或过期，请刷新重新输入");
        }

        //redis中获取到的图片验证码的值
        String imageCodeValueFromRedis = imageCodeAjaxResult.getResultObj().toString();
        if(!imageCodeValueFromRedis.toLowerCase().trim().equals(imageCode.toLowerCase().trim())){
            throw new RuntimeException("图片验证码错误，请刷新重新输入");
        }

        //当前发送时间
        Date now = new Date();

        //手机验证码的值
        String SMSCodeValue = null;

        //验证码发送记录在Redis的key
        String SMSCodeKeyInRedis = "sms:"+mobile;

        //3.获取上一次的手机验证码发送记录
        AjaxResult lastSMSCodeResult = redisFeignClient.getString(SMSCodeKeyInRedis);

        //判断是否有上一次
        if(lastSMSCodeResult.isSuccess() && lastSMSCodeResult.getResultObj() != null){
            //3.1.上一次有发送
            SMSCodeVo smsCodeVo = JSON.parseObject(lastSMSCodeResult.getResultObj().toString(), SMSCodeVo.class);
            //1.判断上一次发送时间和现在时间是否发送频繁：上一次发送时间和当前发送时间差要大于 60s
            Date lastDate = smsCodeVo.getDate();
            //2.如果咩有过60s，报异常，返回提示信息
            if(now.getTime()/1000 - lastDate.getTime()/1000 < 60){
                throw new RuntimeException("发送频繁，请稍后重试");
            }

            //3.如果过了60s,获取上一次发送的证码的值
            SMSCodeValue = smsCodeVo.getCode();
        }else {

            //3.2.上一次没发送
            //1.创建手机验证码
            SMSCodeValue = StrUtils.getRandomString(4);
        }


        //4.存储手机验证码发送记录Redis(mysql),设置过期时间5分钟：怎么存(key？)，存哪些内容
        //后台生成key:格式 sms:18244229575 =  {验证码值 ，发送时间} - SMSCodeVo -JSON
        //String SMSCodeKeyInRedis = "sms:"+mobile;

        Date date = new Date();
        //把验证码发送记录封装成vo,把vo转成json
        SMSCodeVo smsCodeVo = new SMSCodeVo(SMSCodeValue,date);
        String smsCodeJson = JSON.toJSONString(smsCodeVo);

        //手机验证码发送记录Redis
        AjaxResult smsCodeResult = redisFeignClient.setex(SMSCodeKeyInRedis, 600, smsCodeJson);
        if(!smsCodeResult.isSuccess()){
            throw new RuntimeException("手机验证码发送失败[缓存服务不可用]，请稍后重试 。");
        }

        //发送验证码到目标手机(短信网关)
        String messageContent="您的手机验证码为["+SMSCodeValue+"]，请在5分钟内使用";
        System.out.println(messageContent);

        Map<String, String> map = new HashMap<>();
        map.put("Uid","yandachoupi");
        map.put("Key","d41d8cd98f00b204e980");
        map.put("smsMob",mobile);
        map.put("smsText",messageContent);
        String result = HttpUtil.sendPost("http://utf8.api.smschinese.cn/", map);
        if(StringUtils.hasLength(result) && Integer.valueOf(result) < 0){
            throw new RuntimeException("手机验证码发送失败[错误码："+result+"，请联系管理员]");

        }

    }
}
